import { Transform } from "@rivet/transform";
import type { Plugin, PluginKey } from "./plugin.ts";
import type { PatchState } from "./state.ts";

export type Command = (
  state: PatchState,
  dispatch?: (tr: Transaction) => void,
) => boolean;

export class Transaction extends Transform {
  time: number;

  private meta: { [name: string]: any } = Object.create(null);

  /// @internal
  constructor(state: PatchState) {
    super(state.doc);
    this.time = Date.now();
  }

  setTime(time: number): this {
    this.time = time;
    return this;
  }

  /// Store a metadata property in this transaction, keyed either by
  /// name or by plugin.
  setMeta(key: string | Plugin | PluginKey, value: any): this {
    this.meta[typeof key == "string" ? key : key.key] = value;
    return this;
  }

  getMeta(key: string | Plugin | PluginKey): any {
    return this.meta[typeof key == "string" ? key : key.key];
  }

  get isGeneric(): boolean {
    for (let _ in this.meta) return false;
    return true;
  }
}
